package view.swing;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

import model.events.errors.EndGameError;
import model.events.errors.ErrorEvent;
import model.listeners.ErrorListener;
import util.Constants;
import util.Resources;
import view.IBoardView;
import view.ILogView;
import view.IPlayersView;
import view.IRackView;
import view.swing.help.DistributionWindow;
import view.swing.popup.ErrorMessage;
import controller.ActionController;
import controller.GameController;

@SuppressWarnings("serial")
public class MainWindow extends JFrame implements ErrorListener {
    private JMenuBar menuBar = new JMenuBar();
    private JMenu partieMenu = new JMenu(Resources.getString("Game"));
    private JMenu dictMenu = new JMenu(Resources.getString("Dictionary"));
    private JMenu helpMenu = new JMenu(Resources.getString("Help"));

    private JMenuItem nouvPartie = new JMenuItem(Resources.getString("Actions.NewGame"));
    private JMenuItem finirPartie = new JMenuItem(Resources.getString("Actions.EndGame"));
    private JMenuItem chercheMot = new JMenuItem(Resources.getString("Actions.LookUpWord"));
    private JMenuItem distribHelp = new JMenuItem(Resources.getString("Help.Distribution"));
    private GameController gameController;

    private MainWindow(GameController gc, Component boardPanel,
            Component playersPanel, Component logPanel, Component rackPanel,
            Component buttonsPanel) {
        super(Constants.STR_PROGRAM_NAME + " - " + Constants.STR_AUTHORS);
        this.gameController = gc;
        this.setMinimumSize(new Dimension(800, 600));
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // On initialise le menu
        this.initMenu();
        this.setVisible(true);

        JPanel pane = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.insets = new Insets(2, 2, 2, 2);
        c.weighty = 1;
        c.weightx = 1;
        c.gridx = 0;
        c.gridy = 0;
        c.gridheight = 4;
        c.fill = GridBagConstraints.BOTH; // Use both horizontal & vertical
        pane.add(boardPanel, c);

        c.gridheight = 1;
        c.gridx = 1;
        c.gridy = 0;
        c.gridwidth = 2;
        c.weightx = 0.1;
        c.weighty = 0.3;
        c.fill = GridBagConstraints.BOTH;
        pane.add(playersPanel, c);

        c.gridy = 1;
        c.weighty = 1;
        pane.add(logPanel, c);

        c.gridy = 2;
        c.gridwidth = 1;
        c.weighty = 0.3;
        c.fill = GridBagConstraints.HORIZONTAL;

        pane.add(buttonsPanel, c);

        c.gridy = 3;
        c.gridx = 1;
        c.weighty = 0.1;
        c.gridwidth = 2;
        c.fill = GridBagConstraints.BOTH;
        pane.add(rackPanel, c);
        this.setContentPane(pane);
    }

    public MainWindow(GameController gc, IBoardView view, IPlayersView view2,
            ILogView view3, IRackView view4) {
        this(gc, ((BoardView) view).getPanel(), ((PlayersView) view2)
                .getPanel(), ((LogView) view3).getPanel(), ((RackView) view4)
                .getPanel(), new ButtonsPanel(gc.getActionController()));
    }

    /**
     * Initialise le menu
     * 
     * @param actionController
     */
    private void initMenu() {
        final ActionController actionController = gameController
                .getActionController();
        nouvPartie.setAccelerator(KeyStroke.getKeyStroke('N', Toolkit
                .getDefaultToolkit().getMenuShortcutKeyMask(), false));
        nouvPartie.setMnemonic('N');
        final MainWindow mainWindow = this;
        nouvPartie.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                NewGameWindow ngw = new NewGameWindow(new NewPlayerView(), gameController, mainWindow);
                ngw.pack();
            }
        });
        finirPartie.setAccelerator(KeyStroke.getKeyStroke('Q', Toolkit
                .getDefaultToolkit().getMenuShortcutKeyMask(), false));
        finirPartie.setMnemonic('F');
        finirPartie.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                actionController.endGame();
            }
        });

        partieMenu.add(nouvPartie);
        partieMenu.add(finirPartie);
        partieMenu.setMnemonic('P');

        chercheMot.setAccelerator(KeyStroke.getKeyStroke('F', Toolkit
                .getDefaultToolkit().getMenuShortcutKeyMask(), false));
        chercheMot.setMnemonic('C');
        chercheMot.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                actionController.dictionaryLookup();
            }
        });
        dictMenu.add(chercheMot);
        dictMenu.setMnemonic('D');
        
        distribHelp.setMnemonic('D');
        distribHelp.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                DistributionWindow fenetre = new DistributionWindow(mainWindow, gameController.getBagDistribution());
                fenetre.setVisible(true);
            }
        });
        helpMenu.add(distribHelp);
        helpMenu.setMnemonic('H');

        menuBar.add(partieMenu);
        menuBar.add(dictMenu);
        menuBar.add(helpMenu);

        this.setJMenuBar(menuBar);
    }

    @Override
    public void errorOccured(ErrorEvent event) {
        if (event instanceof EndGameError) {
            gameController.endGame();
        }
        ErrorMessage em = new ErrorMessage(event.getMessage());
        em.setParentWindow(this);
        em.show();
    }
}